package com.example.ortools.start.cp;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: peng.li
 * @date: 2024/07/22
 * @description:
 */
public class InventoryConverter {

        public static void main(String[] args) {
            // 原始数据结构示例
            List<MergeData> req = new ArrayList<>();
            MergeData mergeData = new MergeData();
            mergeData.setGoodsSpecCombinationROList(Arrays.asList(
                    new GoodsSpecCombinationRO(11L,null,"规格1",new BigDecimal("2"),new BigDecimal("8"),null),
                    new GoodsSpecCombinationRO(22L,null,"规格2",new BigDecimal("1"),new BigDecimal("6"),null),
                    new GoodsSpecCombinationRO(33L,null,"规格3",new BigDecimal("1"),new BigDecimal("5"),null)
            ));
            MergeData mergeData1 = new MergeData();
            mergeData1.setGoodsSpecCombinationROList(Arrays.asList(
                    new GoodsSpecCombinationRO(33L,null,"规格3",new BigDecimal("1"),new BigDecimal("5"),null),
                    new GoodsSpecCombinationRO(44L,null,"规格4",new BigDecimal("1"),new BigDecimal("4"),null)
            ));
            MergeData mergeData2 = new MergeData();
            mergeData2.setGoodsSpecCombinationROList(Arrays.asList(
                    new GoodsSpecCombinationRO(55L,null,"规格5",new BigDecimal("1"),new BigDecimal("153"),null),
                    new GoodsSpecCombinationRO(66L,null,"规格6",new BigDecimal("3"),new BigDecimal("61"),null)
            ));
            MergeData mergeData3 = new MergeData();
            mergeData3.setGoodsSpecCombinationROList(Arrays.asList(
                    new GoodsSpecCombinationRO(44L,null,"规格4",new BigDecimal("1"),new BigDecimal("4"),null),
                    new GoodsSpecCombinationRO(77L,null,"规格7",new BigDecimal("3"),new BigDecimal("5"),null)
            ));
            req.add(mergeData);
            req.add(mergeData1);
            req.add(mergeData2);
            req.add(mergeData3);
            System.out.println(JSON.toJSONString(req));
            //规格id最大数量限制
            Map<Long, BigDecimal> specIdMaxNumLimit = new HashMap<>();
            specIdMaxNumLimit.put(11L,new BigDecimal("3242123"));
            specIdMaxNumLimit.put(22L,new BigDecimal("4382446"));
            specIdMaxNumLimit.put(33L,new BigDecimal("2647121"));
            specIdMaxNumLimit.put(44L,new BigDecimal("2284643"));
            specIdMaxNumLimit.put(55L,new BigDecimal("4827343"));
            specIdMaxNumLimit.put(66L,new BigDecimal("7923423"));
            specIdMaxNumLimit.put(77L,new BigDecimal("2342891"));
            //规格id拆零单位数据
            Map<Long, BigDecimal> specIdSingleNum = new HashMap<>();
            specIdSingleNum.put(11L, BigDecimal.valueOf(8));
            specIdSingleNum.put(22L, BigDecimal.valueOf(6));
            specIdSingleNum.put(33L, BigDecimal.valueOf(5));
            specIdSingleNum.put(44L, BigDecimal.valueOf(4));
            specIdSingleNum.put(55L, BigDecimal.valueOf(153));
            specIdSingleNum.put(66L, BigDecimal.valueOf(61));
            specIdSingleNum.put(77L, BigDecimal.valueOf(5));
            //规格id最大整包数量
            Map<Long, Integer> specIdMaxIntNum = new HashMap<>();
            for (Long key : specIdMaxNumLimit.keySet()) {
                specIdMaxIntNum.put(key, specIdMaxNumLimit.get(key).divide(specIdSingleNum.get(key), BigDecimal.ROUND_DOWN).intValue());
            }
            // 转换数据结构
            List<MergeData> transformedList = transformToDesiredStructure(req);
            // 打印转换后的数据结构
            System.out.println(JSON.toJSONString(transformedList));
            CpDealDlyEmample.cpSolver(specIdMaxIntNum,transformedList);
            System.out.println("****************************************************");
            MIPDealDlyEmample.cpSolver(specIdMaxIntNum,transformedList);

        }

    public static List<MergeData> transformToDesiredStructure(List<MergeData> req) {
        Map<Set<Long>,Integer> groupMap = new HashMap<>();
        Integer initGroupId = 0;
        for (MergeData maps : req) {
            Set<Long> keyBuilder = new HashSet<>();
            for (GoodsSpecCombinationRO goodsSpecCombinationRO : maps.getGoodsSpecCombinationROList()) {
                keyBuilder.add(goodsSpecCombinationRO.getGoodsSpecId());
            }
            boolean hasKey = false;
            for (Map.Entry<Set<Long>, Integer> entry : groupMap.entrySet()) {
                Set<Long> key = entry.getKey();
                //获取keyBuilder与key的交集
                Set<Long> intersection = new HashSet<>(keyBuilder);
                intersection.retainAll(key);
                //获取keyBuilder与key的并集
                Set<Long> union = new HashSet<>(keyBuilder);
                union.addAll(key);
                if(intersection.size()>0){
                    groupMap.remove(key);
                    groupMap.put(union,entry.getValue());
                    maps.setShardSpecIds(intersection);
                    maps.setGroupId(entry.getValue());
                    hasKey = true;
                    break;
                }
            }
            if(!hasKey){
                groupMap.put(keyBuilder,++initGroupId);
                maps.setGroupId(initGroupId);
            }
        }
        //用stream的形式将req按照groupId进行分组,并返回Map<Integer,List>
        Map<Integer, List<MergeData>> listMap = req.stream().collect(Collectors.groupingBy(MergeData::getGroupId));
        //key为共享的id,value为序号,默认从0开始
        Map<Long,Integer> sharedIdSeqMap = new HashMap<>();
        if (listMap != null) {
            for (List<MergeData> list : listMap.values()) {
                //获取list里面所有Set<Long> shardSpecIds里面的并集数据
                Set<Long> union = new HashSet<>();
                for (MergeData mergeData : list) {
                    if(mergeData.getShardSpecIds()!=null) {
                        union.addAll(mergeData.getShardSpecIds());
                    }
                }
                union.forEach(data->sharedIdSeqMap.put(data,0));
                for (MergeData mergeData : list) {
                    mergeData.setShardSpecIds(union);
                }
            }
            for (List<MergeData> list : listMap.values()) {
                MergeData firstData = list.get(0);
                //如果没有共享的数据,则不用转换加工处理
                if(CollectionUtils.isEmpty(firstData.getShardSpecIds())){
                    continue;
                }
                for (MergeData mergeData : list) {
                    mergeData.getGoodsSpecCombinationROList().forEach(data->{
                        if(firstData.getShardSpecIds().contains(data.getGoodsSpecId())){
                            data.setShareSpecId(data.getGoodsSpecId());
                            data.setSeq(sharedIdSeqMap.get(data.getGoodsSpecId()));
                            sharedIdSeqMap.put(data.getGoodsSpecId(),sharedIdSeqMap.get(data.getGoodsSpecId())+1);
                        }
                    });
                }
            }
        }
        return req;
    }
}
